import time
import json
import socket
import psutil

from multiprocessing import Process
from .node import Node

nodeName = socket.gethostname()


def dict_to_list(dict_item):
    return list(dict_item.values())


def get_cpu():
    cpu_core = psutil.cpu_count(False)
    cpu_percent = psutil.cpu_percent(1)
    return {'cpu_core': cpu_core, 'cpu_percent': cpu_percent}


def get_memory():
    mem = psutil.virtual_memory()  # 查看内存信息:(total,available,percent,used,free)
    # print(mem)
    mem_total = float('%.2f' % (mem[0] / 1024 / 1024))
    mem_used = float('%.2f' % (mem[3] / 1024 / 1024))
    mem_per = mem[2]
    mem_info = {
        'mem_total': mem_total,
        'mem_used': mem_used,
        'mem_per': mem_per,
    }
    return mem_info


def get_disk():
    disk = psutil.disk_usage('/')
    disk_info = {
        'disk_total': float('%.2f' % (disk[0] / 1024 / 1024)),
        'disk_used': float('%.2f' % (disk[1] / 1024 / 1024)),
        'disk_per': disk[3],
    }
    return disk_info


def get_network():
    # 查看网络流量的信息；(bytes_sent, bytes_recv, packets_sent, packets_recv, errin, errout, dropin, dropout)
    network = psutil.net_io_counters()
    # print(network)
    network_sent = float('%.2f' % (psutil.net_io_counters()[0] / 8 / 1024))
    network_recv = float('%.2f' % (psutil.net_io_counters()[1] / 8 / 1024))  # 每秒接受的kb
    network_info = {
        'network_sent': network_sent,
        'network_recv': network_recv
    }
    return network_info


def get_info():
    # info = {
    #     'cpu': get_cpu(),
    #     'memory': get_memory(),
    #     'disk': get_disk(),
    #     'network': get_network(),
    #     'timestamp': int(time.time())
    # }
    new_info = [float('%.2f' % time.time())] + dict_to_list(get_cpu()) + dict_to_list(get_memory()) + dict_to_list(
        get_disk()) + dict_to_list(get_network())
    return new_info


class StaticNodeLauncher(object):
    def __init__(self, conf):
        self.conf = conf

    def launch(self):
        conf = self.conf
        node = Node(conf)
        node.run()

    def start_resource_watching(self):
        p1 = Process(target=self.watcher, name='watcher', daemon=True)
        p1.start()
        p2 = Process(target=self.receiver, name='receiver', daemon=True)
        p2.start()
        p1.join()
        p2.join()

    def watcher(self):
        cs = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        addr = self.conf['addr']

        while True:
            data = {
                'type': 'client_append_entries',
                'info': {self.conf['id']: get_info()}
            }
            print('send: ', data)

            data = json.dumps(data).encode('utf-8')
            cs.sendto(data, addr)

            time.sleep(self.conf['interval'])

    def receiver(self):
        # 注意，这里必须指定一个固定的recv端口号，否则server无法找到client
        # 这里规定的是10000
        # addr = ('localhost', 10000)
        addr = (self.conf['addr'][0], self.conf['client_port'])
        ss: socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        ss.bind(addr)

        while True:
            data, addr = ss.recvfrom(65535)

            data = json.loads(data)
            with open('../application/data/commit_index', 'w') as f:
                f.write(str(data['index']))
            print('recv: ' + str(data['index']) + ' has been committed')
